package com.ruleengine.db.service.impl;

import java.util.List;
import java.util.Optional;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.ruleengine.db.mapper.RulechainMapper;
import com.ruleengine.db.model.Rulechain;
import com.ruleengine.db.model.RulechainState;
import com.ruleengine.db.model.RulechainStatus;
import com.ruleengine.db.service.RulechainService;

/**
 * @author lianghanwei on 2024/3/17
 */
@Service
public class RulechainServiceImpl extends ServiceImpl<RulechainMapper, Rulechain> implements RulechainService {

    private final RulechainMapper rulechainMapper;

    public RulechainServiceImpl(RulechainMapper rulechainMapper) {
        this.rulechainMapper = rulechainMapper;
    }

    @Override
    public Optional<Rulechain> getRulechain(String tenantId, String rulechainId) {
        return ChainWrappers.lambdaQueryChain(rulechainMapper)
            .eq(Rulechain::getTenantId, tenantId)
            .eq(Rulechain::getRulechainId, rulechainId)
            .ne(Rulechain::getState, RulechainState.DELETED)
            .oneOpt();
    }

    @Override
    public Optional<Rulechain> getRulechain(String rulechainId, int expectedMinVersion, RulechainState state) {
        return ChainWrappers.lambdaQueryChain(rulechainMapper)
            .eq(Rulechain::getRulechainId, rulechainId)
            .ge(Rulechain::getResourceVersion, expectedMinVersion)
            .eq(Rulechain::getState, state)
            .oneOpt();
    }

    @Override
    public List<Rulechain> getRulechains(String tenantId, List<String> rulechainIds) {
        return ChainWrappers.lambdaQueryChain(rulechainMapper)
            .eq(Rulechain::getTenantId, tenantId)
            .ne(Rulechain::getState, RulechainState.DELETED)
            .in(Rulechain::getRulechainId, rulechainIds)
            .list();
    }

    @Override
    public boolean updateRulechainDescriptionAndTopic(String tenantId, String rulechainId, String description, String topic, int expectedVersion) {
        return rulechainMapper.update(
            Rulechain.builder()
                .description(description)
                .topic(topic)
                .resourceVersion(expectedVersion)
                .build(),
            Wrappers.lambdaUpdate(Rulechain.class)
                .eq(Rulechain::getTenantId, tenantId)
                .eq(Rulechain::getRulechainId, rulechainId)
        ) > 0;
    }

    @Override
    public boolean updateRulechainState(String tenantId, String rulechainId, RulechainState state, int expectedVersion) {
        return rulechainMapper.update(
            Rulechain.builder()
                .state(state)
                .resourceVersion(expectedVersion)
                .build(),
            Wrappers.lambdaUpdate(Rulechain.class)
                .eq(Rulechain::getRulechainId, rulechainId)
        ) > 0;
    }

    @Override
    public boolean updateRulechainStatus(String rulechainId, int expectedVersion, RulechainStatus status) {
        return rulechainMapper.update(
            Rulechain.builder()
                .status(status)
                .resourceVersion(expectedVersion)
                .build(),
            Wrappers.lambdaUpdate(Rulechain.class)
                .eq(Rulechain::getRulechainId, rulechainId)
        ) > 0;
    }

    @Override
    public boolean softDeleteRulechains(String tenantId, List<String> rulechainIds) {
        return ChainWrappers.lambdaUpdateChain(rulechainMapper)
            .set(Rulechain::getState, RulechainState.DELETED)
            .set(Rulechain::getStatus, RulechainStatus.DELETED)
            .eq(Rulechain::getTenantId, tenantId)
            .ne(Rulechain::getState, RulechainState.ENABLED)
            .ne(Rulechain::getStatus, RulechainStatus.RUNNING)
            .in(Rulechain::getRulechainId, rulechainIds)
            .update();
    }
}
